package com.hubao.flutter_weight_parser.protocol;


import com.hubao.flutter_weight_parser.protocol.exception.WeightParseException;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.Function;
import org.mozilla.javascript.NativeArray;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.ScriptableObject;

import java.math.BigDecimal;
import java.text.ParseException;
import java.util.Arrays;
import java.util.Optional;


/**
 * JS实现的称重协议
 * <p>
 * 通过加载js文件实现协议动态加载
 */
public class JavaScriptWeightProtocol implements WeightProtocol {

    private final Function addFunction;

    private final Function isCompleteFunction;
    private final Function parseWeightFunction;

    private final Context context;
    private final Scriptable scope;

    private final Scriptable object;


    public JavaScriptWeightProtocol(Context context, Scriptable scope, Scriptable object) {
        this.context = context;
        this.scope = scope;
        this.object = object;
        this.addFunction = (Function) ScriptableObject.getProperty(this.object, "add");
        this.isCompleteFunction = (Function) ScriptableObject.getProperty(this.object, "isComplete");
        this.parseWeightFunction = (Function) ScriptableObject.getProperty(this.object, "parseWeight");
    }

    @Override
    public boolean isAscii() {
        return (boolean) ScriptableObject.getProperty(this.object, "isAscii");
    }

    @Override
    public String getName() {
        return (String) ScriptableObject.getProperty(this.object, "name");
    }

    @Override
    public void add(int data) {
        this.addFunction.call(context, scope, object, new Object[]{data});
        NativeArray obj = (NativeArray) ScriptableObject.getProperty(this.object, "weight");

    }

    @Override
    public boolean isComplete() {
        return (boolean) this.isCompleteFunction.call(context, scope, object, EMPTY_ARRAY);
    }

    @Override
    public Optional<BigDecimal> parseWeight() {
        try {
            return Optional.ofNullable(this.parseWeightFunction.call(context, scope, this.object, EMPTY_ARRAY)).map(o -> new BigDecimal(String.valueOf(o)));
        } catch (Exception e) {
            NativeArray obj = (NativeArray) ScriptableObject.getProperty(this.object, "weight");
            throw new WeightParseException(this.getName(), obj);
        }
    }
}

